#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>

#if defined(LINUX)
#include <unistd.h>  
#include <sys/time.h>
#include <pthread.h>
#include <dirent.h>  
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/reboot.h>
#include <linux/rtnetlink.h>
#include <sys/wait.h>  
#include <errno.h>
#else
#include <io.h>
#include <direct.h>
#include <Iphlpapi.h>
#pragma warning(disable:4996)
#define snprintf _snprintf
#endif


#include "Logging.h"
#include "ArrayList.h"
#include "TcpServerClient.h"

#if !defined(LINUX)
#pragma  warning(disable:4996)
#endif

ARRAYLIST      al;  // 客户端队列
NAMELIST       n1;  // 已登录的客户端名字

int ArrayListInit(ARRAYLIST *lst,unsigned int max)  // 构造一个空列表
{
    lst->data =(ITEMDATA *)malloc( (size_t)max * sizeof(ITEMDATA) );
    if( lst->data == NULL ) 
    {
        WriteFileLog(LERROR,"Allocate memory error , the ArrayList initialization failed program exits !");
        exit(0);
    }
    #if defined(LINUX)
    if( pthread_mutex_init(&lst->hMutex,NULL) != 0 )
    #else
    if( ( lst->hMutex = CreateMutex(NULL, FALSE, NULL) ) == NULL )
    #endif
    {
        WriteFileLog(LERROR,"Create a mutex lock fails, the program exits !");
        if( lst->data ) 
        {
            free(lst->data);
        }
        exit(0);
    }    
    lst->maxnum = max;
    lst->num    = 0;
    WriteFileLog(LHINT,"Construct an ArrayList is complete !");
    return(1);
}

int NameListInit(NAMELIST *lst, unsigned int max)  // 构造一个空列表
{
	lst->data = (char **)malloc((size_t)max * CLIENTNAME_SIZE);
	if (lst->data == NULL)
	{
		WriteFileLog(LERROR, "Allocate memory error , the NameList initialization failed program exits !");
		exit(0);
	}
#if defined(LINUX)
	if (pthread_mutex_init(&lst->hMutex, NULL) != 0)
#else
	if ((lst->hMutex = CreateMutex(NULL, FALSE, NULL)) == NULL)
#endif
	{
		WriteFileLog(LERROR, "Create a mutex lock fails, the program exits !");
		if (lst->data)
		{
			free(lst->data);
		}
		exit(0);
	}
	lst->maxnum = max;
	lst->num = 0;
	WriteFileLog(LHINT, "Construct an NameList is complete !");
	return(1);
}

void ArrayListDestroy(ARRAYLIST *lst)   // 销毁列表
{ 
    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( lst->data ) 
    {
        free(lst->data);
    }
    lst->data = NULL;
    lst->num   = 0;

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    #if defined(LINUX)
    pthread_mutex_destroy(&lst->hMutex);
    #else
    CloseHandle(lst->hMutex);
    #endif

    WriteFileLog(LHINT,"ArrayList cleared !");
}

void NameListDestroy(NAMELIST *lst)   // 销毁列表
{
#if defined(LINUX)
	pthread_mutex_lock(&lst->hMutex);
#else
	WaitForSingleObject(lst->hMutex, INFINITE);
#endif

	if (lst->data)
	{
		free(lst->data);
	}
	lst->data = NULL;
	lst->num = 0;

#if defined(LINUX)
	pthread_mutex_unlock(&lst->hMutex);
#else
	ReleaseMutex(lst->hMutex);
#endif

#if defined(LINUX)
	pthread_mutex_destroy(&lst->hMutex);
#else
	CloseHandle(lst->hMutex);
#endif

	WriteFileLog(LHINT, "NameList cleared !");
}

void ArrayListClear(ARRAYLIST *lst)   // 清为空列表
{ 
    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    lst->num   = 0;

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif
}

void NameListClear(NAMELIST *lst)   // 清为空列表
{
#if defined(LINUX)
	pthread_mutex_lock(&lst->hMutex);
#else
	WaitForSingleObject(lst->hMutex, INFINITE);
#endif

	lst->num = 0;

#if defined(LINUX)
	pthread_mutex_unlock(&lst->hMutex);
#else
	ReleaseMutex(lst->hMutex);
#endif
}

int ArrayListIsEmpty(ARRAYLIST *lst)   // 若列表为空列表,则返回1,否则返回0 
{
    if( lst->num == 0 ) 
    {
        return(1);
    }
    else
    {
        return(0);
    }
}

int ArrayListLength(ARRAYLIST *lst)   // 返回列表的长度 
{
    return(lst->num);
}

int ArrayListInsert(ARRAYLIST *lst,int fd,char *name,char *ip,unsigned short port)    // 插入列表 
{
    size_t i,j;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( lst->num > ( lst->maxnum - 1 ) ) 
    {
        #if defined(LINUX)
        pthread_mutex_unlock(&lst->hMutex);
        #else
        ReleaseMutex(lst->hMutex);
        #endif
        WriteFileLog(LERROR,"The client number has reached the maximum allowed, insert failure.");
        return(0);
    }

    for(i=0;i<lst->num;i++)
    {
        if( lst->data[i].fd == fd )
        {
            for(j=i;j<(lst->num-1);j++)
            {
                memcpy(&(lst->data[j]),&(lst->data[j+1]),sizeof(ITEMDATA));
            }
            (lst->num)--;
            shutdown(fd,2); 
            Close(fd);
            #if defined(LINUX)
            pthread_mutex_unlock(&lst->hMutex);
            #else
            ReleaseMutex(lst->hMutex);
            #endif
            WriteFileLog(LFATAL,"The client socket conflict, shut down the existing socket.");
            return(0);
        }
    }

    ITEMDATA dat;
    dat.fd = fd;
    memset(dat.name,0,sizeof(dat.name));
    dat.logined = 0;
    memset(dat.ip,0,sizeof(dat.ip));
    memcpy(dat.ip,ip,19);
    dat.port = port;
    dat.activetime = GetTimeVal();

    memcpy(&(lst->data[lst->num]),&dat,sizeof(ITEMDATA));
    (lst->num)++;

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(1);
}

int NameListInsert(NAMELIST *lst, char *name)    // 插入列表 
{
	size_t i, j;

#if defined(LINUX)
	pthread_mutex_lock(&lst->hMutex);
#else
	WaitForSingleObject(lst->hMutex, INFINITE);
#endif

	if (lst->num > (lst->maxnum - 1))
	{
#if defined(LINUX)
		pthread_mutex_unlock(&lst->hMutex);
#else
		ReleaseMutex(lst->hMutex);
#endif
		WriteFileLog(LERROR, "The client number has reached the maximum allowed, insert failure.");
		return(0);
	}

	for (i = 0; i < lst->num; i++)
	{
		if (strcmp(lst->data[i],name)==0)
		{
			for (j = i; j < (lst->num - 1); j++)
			{
				memcpy((lst->data[j]), (lst->data[j + 1]), CLIENTNAME_SIZE);
			}
			(lst->num)--;
			//shutdown(fd, 2);
			//Close(fd);
#if defined(LINUX)
			pthread_mutex_unlock(&lst->hMutex);
#else
			ReleaseMutex(lst->hMutex);
#endif
			WriteFileLog(LFATAL, "The client Name conflict, clear the existing socket.");
			return(0);
		}
	}

	memcpy((lst->data[lst->num]), name, CLIENTNAME_SIZE);
	(lst->num)++;

#if defined(LINUX)
	pthread_mutex_unlock(&lst->hMutex);
#else
	ReleaseMutex(lst->hMutex);
#endif

	return(1);
}

int  ArrayListDelete(ARRAYLIST *lst,ITEMDATA *dat)   // 删除列表记录 
{
    size_t i,j;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( (lst->num) < 1 )
    {
        #if defined(LINUX)
        pthread_mutex_unlock(&lst->hMutex);
        #else
        ReleaseMutex(lst->hMutex);
        #endif
        return(0);
    }

    for(i=0;i<lst->num;i++)
    {
        if( memcmp(&(lst->data[i]),dat,sizeof(ITEMDATA)) == 0 )
        {
            for(j=i;j<(lst->num-1);j++)
            {
                memcpy(&(lst->data[j]),&(lst->data[j+1]),sizeof(ITEMDATA));
            }
            (lst->num)--;
            #if defined(LINUX)
            pthread_mutex_unlock(&lst->hMutex);
            #else
            ReleaseMutex(lst->hMutex);
            #endif
            return(1);
        }
        
    }

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(0);
}

int  NameListDelete(NAMELIST *lst, char* name)   // 删除列表记录 
{
	size_t i, j;

#if defined(LINUX)
	pthread_mutex_lock(&lst->hMutex);
#else
	WaitForSingleObject(lst->hMutex, INFINITE);
#endif

	if ((lst->num) < 1)
	{
#if defined(LINUX)
		pthread_mutex_unlock(&lst->hMutex);
#else
		ReleaseMutex(lst->hMutex);
#endif
		return(0);
	}

	for (i = 0; i < lst->num; i++)
	{
		if (strcmp((lst->data[i]), name) == 0)
		{
			for (j = i; j < (lst->num - 1); j++)
			{
				memcpy((lst->data[j]), (lst->data[j + 1]), CLIENTNAME_SIZE);
			}
			(lst->num)--;
#if defined(LINUX)
			pthread_mutex_unlock(&lst->hMutex);
#else
			ReleaseMutex(lst->hMutex);
#endif
			return(1);
		}

	}

#if defined(LINUX)
	pthread_mutex_unlock(&lst->hMutex);
#else
	ReleaseMutex(lst->hMutex);
#endif

	return(0);
}

int ArrayListDeleteByFD(ARRAYLIST *lst,int fd)        // 删除列表记录 
{
    size_t i,j;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( lst->num < 1 )
    {
        #if defined(LINUX)
        pthread_mutex_unlock(&lst->hMutex);
        #else
        ReleaseMutex(lst->hMutex);
        #endif
        return(0);
    }

    for(i=0;i<lst->num;i++)
    {
        if( lst->data[i].fd == fd )
        {
            for(j=i;j<(lst->num-1);j++)
            {
                memcpy(&(lst->data[j]),&(lst->data[j+1]),sizeof(ITEMDATA));
            }
            (lst->num)--;
            #if defined(LINUX)
            pthread_mutex_unlock(&lst->hMutex);
            #else
            ReleaseMutex(lst->hMutex);
            #endif
            return(1);
        }
        
    }

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(0);
}

int ArrayListUpdateActive(ARRAYLIST *lst,int fd)        // 更新记录活动时间
{
    size_t i;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( lst->num < 1 )
    {
        #if defined(LINUX)
        pthread_mutex_unlock(&lst->hMutex);
        #else
        ReleaseMutex(lst->hMutex);
        #endif
        return(0);
    }

    for(i=0;i<lst->num;i++)
    {
        if( lst->data[i].fd == fd )
        {
            lst->data[i].activetime = GetTimeVal();
            #if defined(LINUX)
            pthread_mutex_unlock(&lst->hMutex);
            #else
            ReleaseMutex(lst->hMutex);
            #endif
            return(1);
        }
    }

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(0);
}

int ArrayListUpdateLogin(ARRAYLIST *lst,int fd,char *name,int conflict)        // 更新记录登陆状态
{
    size_t i;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    if( lst->num < 1 )
    {
        #if defined(LINUX)
        pthread_mutex_unlock(&lst->hMutex);
        #else
        ReleaseMutex(lst->hMutex);
        #endif
        return(0);
    }

    for(i=0;i<lst->num;i++)
    {
        if( strcmp(lst->data[i].name,name) == 0 )
        {
            if( conflict == 0 )
            {
                #if defined(LINUX)
                pthread_mutex_unlock(&lst->hMutex);
                #else
                ReleaseMutex(lst->hMutex);
                #endif
                WriteFileLog(LERROR,"The client already exists, login failure.");
                return(0);
            }
            else
            {
                char czTemp[1024];
                strcpy(czTemp,"{\"Name\":\"Exist\",\"Receiver\":\"\",\"Param\":\"\"}");
                //if( lst->data[i].iswebsocket == 0 )
                {
                    if( TcpSocketWrite(lst->data[i].fd,czTemp,strlen(czTemp)) <= 0 )
                    {
                        shutdown(lst->data[i].fd,2); 
                        Close(lst->data[i].fd);
                        #if defined(LINUX)
                        pthread_mutex_unlock(&lst->hMutex);
                        #else
                        ReleaseMutex(lst->hMutex);
                        #endif
                        WriteFileLog(LERROR,"The client already exists, login failure.");
                        return(0);
                    }
                }
                WriteFileLog(LERROR,"The client already exists, disconnect the existing client.");
                #if defined(LINUX)
                pthread_mutex_unlock(&lst->hMutex);
                #else
                ReleaseMutex(lst->hMutex);
                #endif
                return(0);
            }
        }
    }

    for(i=0;i<lst->num;i++)
    {
        if( lst->data[i].fd == fd )
        {
            strcpy(lst->data[i].name,name);
            lst->data[i].logined = 1;
            #if defined(LINUX)
            pthread_mutex_unlock(&lst->hMutex);
            #else
            ReleaseMutex(lst->hMutex);
            #endif
            return(1);
        }
    }

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(0);
}

int ArrayListDisplay(ARRAYLIST *lst,void (*func)(ARRAYLIST *ls))   // 显示列表
{
    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    (*func)(lst);

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return 1;
}

int NameToFd(ARRAYLIST *lst,char *name)    //通过名字在列表中查询设备号
{
    size_t i,ret = 0;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    for(i=0;i<lst->num;i++)
    {
        if( strcmp(lst->data[i].name,name) == 0 )
        {
            ret = lst->data[i].fd;
            break;
        }
    }

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(ret);
}

int ArrayListUpdateByInt(ARRAYLIST *lst,int id,ITEMDATA *dat,int (*func)(ARRAYLIST *l,int i,ITEMDATA *d))   // 更新列表 
{
    int ret;
    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    ret = (*func)(lst,id,dat);

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(ret);
}

int ArrayListFindByInt(ARRAYLIST *lst,int id,ITEMDATA *dat,int (*func)(ARRAYLIST *l,int i,ITEMDATA *d))   // 查找列表 
{
    int ret;
    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    ret = (*func)(lst,id,dat);

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(ret);
}

int ArrayListCallback(ARRAYLIST *lst,int (*func)(ARRAYLIST *l))   // 列表功能回调函数
{
    int ret;

    #if defined(LINUX)
    pthread_mutex_lock(&lst->hMutex);
    #else
    WaitForSingleObject(lst->hMutex, INFINITE);
    #endif

    ret = (*func)(lst);

    #if defined(LINUX)
    pthread_mutex_unlock(&lst->hMutex);
    #else
    ReleaseMutex(lst->hMutex);
    #endif

    return(ret);
}

